/*
 * Copyright [2022] [https://www.xiaonuo.vip]
 *
 * Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：
 *
 * 1.请不要删除和修改根目录下的LICENSE文件。
 * 2.请不要删除和修改Snowy源码头部的版权声明。
 * 3.本项目代码可免费商业使用，商业使用请保留源码和相关描述文件的项目出处，作者声明等。
 * 4.分发源码时候，请注明软件出处 https://www.xiaonuo.vip
 * 5.不可二次分发开源参与同类竞品，如有想法可联系团队xiaonuobase@qq.com商议合作。
 * 6.若您的项目无法满足以上几点，需要更多功能代码，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.biz.modular.canteen.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.xiaonuo.biz.modular.approval.entity.BizApproval;
import vip.xiaonuo.biz.modular.approval.service.BizApprovalService;
import vip.xiaonuo.biz.modular.approvalorder.enums.BizApprovalCafeteriaTypeEnum;
import vip.xiaonuo.biz.modular.canteen.entity.BizCanteen;
import vip.xiaonuo.biz.modular.canteen.mapper.BizCanteenMapper;
import vip.xiaonuo.biz.modular.canteen.param.*;
import vip.xiaonuo.biz.modular.canteen.result.BizCanteenResult;
import vip.xiaonuo.biz.modular.canteen.service.BizCanteenService;
import vip.xiaonuo.biz.modular.relation.enums.BizRelationCategoryEnum;
import vip.xiaonuo.biz.modular.relation.service.BizRelationService;
import vip.xiaonuo.biz.modular.user.entity.BizUser;
import vip.xiaonuo.biz.modular.user.service.BizUserService;
import vip.xiaonuo.common.cache.CommonCacheOperator;
import vip.xiaonuo.common.enums.CommonSortOrderEnum;
import vip.xiaonuo.common.enums.CommonSwitchEnum;
import vip.xiaonuo.common.exception.CommonException;
import vip.xiaonuo.common.page.CommonPageRequest;
import vip.xiaonuo.dev.api.DevFileApi;

import java.time.LocalTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static vip.xiaonuo.common.consts.CacheConstant.BIZ_CANTEEN_CACHE_KEY;

/**
 * 食堂管理Service接口实现类
 *
 * @author fqa
 * @date 2025/05/09 17:17
 **/
@Service
public class BizCanteenServiceImpl extends ServiceImpl<BizCanteenMapper, BizCanteen> implements BizCanteenService {
    @Resource
    private BizUserService userService;
    @Resource
    private DevFileApi devFileApi;
    @Resource
    private CommonCacheOperator commonCacheOperator;

    @Resource
    private BizRelationService bizRelationService;

    @Override
    public Page<BizCanteen> page(BizCanteenPageParam bizCanteenPageParam) {
        QueryWrapper<BizCanteen> queryWrapper = new QueryWrapper<BizCanteen>().checkSqlInjection();
        if (ObjectUtil.isNotEmpty(bizCanteenPageParam.getCanteenName())) {
            queryWrapper.lambda().like(BizCanteen::getCanteenName, bizCanteenPageParam.getCanteenName());
        }
        if (ObjectUtil.isAllNotEmpty(bizCanteenPageParam.getSortField(), bizCanteenPageParam.getSortOrder())) {
            CommonSortOrderEnum.validate(bizCanteenPageParam.getSortOrder());
            queryWrapper.orderBy(true, bizCanteenPageParam.getSortOrder().equals(CommonSortOrderEnum.ASC.getValue()),
                    StrUtil.toUnderlineCase(bizCanteenPageParam.getSortField()));
        } else {
            queryWrapper.lambda().orderByAsc(BizCanteen::getId);
        }
        return this.page(CommonPageRequest.defaultPage(), queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(BizCanteenAddParam bizCanteenAddParam) {
        BizCanteen bizCanteen = BeanUtil.toBean(bizCanteenAddParam, BizCanteen.class);
        JSONObject json = new JSONObject();
        BizUser bizUser = userService.queryEntity(bizCanteenAddParam.getDirectorId());
        json.put("directorName", bizUser.getName());
        json.put("directorPhone", bizUser.getPhone());
        bizCanteen.setExtJson(json.toJSONString());
        cn.hutool.json.JSONObject fileInfo = devFileApi.getFileInfoById(bizCanteen.getMerchantPrivateKey());
        bizCanteen.setMerchantPrivateKeyUrl(fileInfo.getStr("storagePath"));
        this.save(bizCanteen);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(BizCanteenEditParam bizCanteenEditParam) {
        BizCanteen bizCanteen = this.queryEntity(bizCanteenEditParam.getId());
        if (!Objects.equals(bizCanteenEditParam.getMerchantPrivateKey(), bizCanteen.getMerchantPrivateKey())) {
            cn.hutool.json.JSONObject fileInfo = devFileApi.getFileInfoById(bizCanteenEditParam.getMerchantPrivateKey());
            bizCanteen.setMerchantPrivateKeyUrl(fileInfo.getStr("storagePath"));
        }
        BeanUtil.copyProperties(bizCanteenEditParam, bizCanteen);
        JSONObject json = bizCanteen.getExtJsonObject();
        BizUser bizUser = userService.queryEntity(bizCanteenEditParam.getDirectorId());
        json.put("directorName", bizUser.getName());
        json.put("directorPhone", bizUser.getPhone());
        bizCanteen.setExtJson(json.toJSONString());
        this.updateById(bizCanteen);
        commonCacheOperator.remove(StrUtil.format(BIZ_CANTEEN_CACHE_KEY, bizCanteenEditParam.getId()));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<BizCanteenIdParam> bizCanteenIdParamList) {
        // 执行删除
        this.removeByIds(CollStreamUtil.toList(bizCanteenIdParamList, BizCanteenIdParam::getId));
    }

    @Override
    public BizCanteen detail(BizCanteenIdParam bizCanteenIdParam) {
        return this.queryEntity(bizCanteenIdParam.getId());
    }

    @Resource
    private BizApprovalService approvalService;


    private BizApprovalCafeteriaTypeEnum CanteenCatTimeJudge(BizCanteen bizCanteen) {
        LocalTime nowTime = LocalTime.now();
        if (nowTime.isAfter(bizCanteen.getLunchBeginTime().toLocalTime()) && nowTime.isBefore(bizCanteen.getLunchEndTime().toLocalTime())) {
            return BizApprovalCafeteriaTypeEnum.LUNCH;
        }
        if (nowTime.isAfter(bizCanteen.getDinerBeginTime().toLocalTime()) && nowTime.isBefore(bizCanteen.getDinerEndTime().toLocalTime())) {
            return BizApprovalCafeteriaTypeEnum.SUPPER;
        }
        throw new CommonException("当前时间不在就餐时间段内");
    }

    @Override
    public BizCanteenResult canteenInfo(BizCanteenIdParam bizCanteenIdParam) {
        BizCanteen bizCanteen = this.queryEntity(bizCanteenIdParam.getId());
        BizApprovalCafeteriaTypeEnum cafeteriaTypeEnum = CanteenCatTimeJudge(bizCanteen);
        BizCanteenResult result = BeanUtil.toBean(bizCanteen, BizCanteenResult.class);
        BizApproval approvalSign = approvalService.getApprovalSign(bizCanteenIdParam.getId(), cafeteriaTypeEnum.getValue());
        if (ObjectUtil.isEmpty(approvalSign)) {
            throw new CommonException(StrUtil.format("当前餐厅，今日未申请{}就餐", cafeteriaTypeEnum.getInfo()));
        }
        if (Objects.equals(cafeteriaTypeEnum.getValue(), BizApprovalCafeteriaTypeEnum.LUNCH.getValue())) {
            if (Objects.equals(approvalSign.getIsLunchEat(), CommonSwitchEnum.TRUE.getValue())) {
                throw new CommonException("该审批单已生成午餐订单");
            }
            result.setIsLunch(true);
        } else {
            if (Objects.equals(approvalSign.getIsSupperEat(), CommonSwitchEnum.TRUE.getValue())) {
                throw new CommonException("该审批单已生成晚餐订单");
            }
            result.setIsLunch(false);
        }
        result.setApprovalId(approvalSign.getId());
        result.setOrgName(approvalSign.getVisitDeptName());
        return result;
    }

    @Override
    public BizCanteen queryEntity(String id) {
        BizCanteen bizCanteen = this.getById(id);
        if (ObjectUtil.isEmpty(bizCanteen)) {
            throw new CommonException("食堂管理不存在，id值为：{}", id);
        }
        return bizCanteen;
    }

    @Override
    public List<BizCanteenResult> canteenList(BizCanteenListParam bizCanteenListParam) {
        QueryWrapper<BizCanteen> queryWrapper = new QueryWrapper<BizCanteen>().checkSqlInjection();
        if(ObjectUtil.isNotEmpty(bizCanteenListParam.getOrgId())){
            List<String> canteenIds = bizRelationService.getRelationTargetIdListByObjectIdAndCategory(bizCanteenListParam.getOrgId(),  BizRelationCategoryEnum.BIZ_ORG_CANTEEN_DATA.getValue());
            if (ObjectUtil.isEmpty(canteenIds)) {
                return CollectionUtil.newArrayList();
            }
            queryWrapper.lambda().in(BizCanteen::getId, canteenIds);
        }
        queryWrapper.lambda().orderByAsc(BizCanteen::getId);
        return this.list(queryWrapper).stream().map(bizCanteen -> {
            BizCanteenResult result = new BizCanteenResult();
            BeanUtil.copyProperties(bizCanteen, result);
            return result;
        }).collect(Collectors.toList());
    }

    @Override
    public BizUser getCanteenUserByCanteenId(String canteenId) {
        return this.baseMapper.getCanteenUserByCanteenId(canteenId);
    }

    @Override
    public BizCanteen getCacheBizCanteen(String canteenId) {
        Object o = commonCacheOperator.get(StrUtil.format(BIZ_CANTEEN_CACHE_KEY, canteenId));
        if (ObjectUtil.isNotEmpty(o)) {
            String jsonString = JSON.toJSONString(o);
            return JSONObject.parseObject(jsonString, BizCanteen.class);
        }
        BizCanteen bizCanteen = queryEntity(canteenId);
        commonCacheOperator.put(StrUtil.format(BIZ_CANTEEN_CACHE_KEY, canteenId), bizCanteen, 604800);
        return bizCanteen;
    }

    @Override
    public List<BizCanteen> getBizCanteenList(BizCanteenListByIdParam canteenListParam) {
        if (ObjectUtil.isEmpty(canteenListParam.getIdList())) {
            return CollectionUtil.newArrayList();
        }
        QueryWrapper<BizCanteen> queryWrapper = new QueryWrapper<BizCanteen>().checkSqlInjection();
        queryWrapper.lambda().in(BizCanteen::getId, canteenListParam.getIdList());
        queryWrapper.lambda().orderByAsc(BizCanteen::getId);
        queryWrapper.lambda().select(BizCanteen::getId, BizCanteen::getCanteenName);
        return this.list(queryWrapper);
    }
}
